

#include <baseitemmodel.h>
#include <stdio.h>
#include <assert.h>

BaseItem::BaseItem (BaseItem* parent)
  : _parent(parent)
  , _model(0)
  , _data (0)
{
  _children.clear ();
  if (_parent)
    {
      _parent->Add (this);
    }
}

void BaseItem::SetData(void *data)
{
  _data = data;
}

BaseItem* BaseItem::Find(void *data)
{
  if (_data == data)
    {
      return this;
    }
  foreach (BaseItem* child, _children)
    {
      BaseItem* d = child->Find(data);
      if (d)
        {
          return d;
        }
    }

  return 0;
}

void BaseItem::Add (BaseItem* item)
{
  if (_children.contains(item))
    {
      return;
    }

  item->_parent = this;
  item->_model  = _model;
  _children.push_back (item);

  BaseItemModel* model = GetModel();
  if (model)
    {
      model->AddItem (item);
    }
}

void BaseItem::Remove (BaseItem* item)
{
  if (!_children.contains(item))
    {
      return;
    }

  BaseItemModel* model = GetModel();
  if (model)
    {
      model->RemoveItem (item);
    }

  item->_parent = 0;
  item->_model = 0;
  _children.removeAll(item);
}

void BaseItem::RemoveSelf()
{
  assert (_parent);
  _parent->Remove(this);
}


void BaseItem::SetModel (BaseItemModel* model)
{
  _model = model;
}

BaseItemModel* BaseItem::GetModel()
{
  if (!_model && _parent)
    {
      _model = _parent->GetModel();
    }

  return _model;
}


int BaseItem::GetNumberOfItems () const
{
  return _children.size();
}

int BaseItem::GetIndexOf (BaseItem* item)
{
  return _children.indexOf(item);
}

int BaseItem::GetIndex ()
{
  if (!_parent)
    {
      return 0;
    }
  return _parent->GetIndexOf(this);
}

BaseItem* BaseItem::GetItem (int idx)
{
  if (idx < 0 || idx >= _children.size())
    {
      return 0;
    }
  return _children[idx];
}

BaseItem* BaseItem::GetParent () 
{
  return _parent;
}

QVariant BaseItem::GetData (int column, int role)
{
  return QVariant ();
}

void BaseItem::EnableActions()
{
}

bool BaseItem::BuildMenu (QMenu* menu)
{
  return false;
}

void BaseItem::Trigger ()
{
}

void BaseItem::TriggerDataChanged()
{
  GetModel()->DataChanged(this);
}

/* ***********************************************
 *      BaseItemModel
 * ***********************************************/

BaseItemModel::BaseItemModel ()
  : QAbstractItemModel ()
  , _columns (1)
{
  _root  = new BaseItem (0);
  _root->SetModel(this);
}

BaseItem* BaseItemModel::GetRoot ()
{
  return _root;
}

BaseItem* BaseItemModel::GetItem(const QModelIndex& index)
{
  if (!index.isValid ())
    {
      return 0;
    }

  return static_cast<BaseItem*>(index.internalPointer ());
}

void BaseItemModel::AddItem(BaseItem *item)
{
  int row = item->GetIndex();
  beginInsertRows(
        CreateModelIndex(item->GetParent()),
        row,
        row);
  endInsertRows();
}

void BaseItemModel::RemoveItem(BaseItem *item)
{
  int row = item->GetIndex();
  beginRemoveRows(
        CreateModelIndex(item->GetParent()),
        row,
        row);
  endRemoveRows();
}

void BaseItemModel::SetNumberOfColumns (int columns)
{
  _columns = columns;
}

int BaseItemModel::GetNumberOfColumns () const
{
  return _columns;
}

void BaseItemModel::DataChanged(BaseItem *item)
{
  emit dataChanged (CreateModelIndex(item, 0), CreateModelIndex(item, _columns-1));
}

QModelIndex BaseItemModel::CreateModelIndex(BaseItem* item, int column) const
{
  return createIndex (item->GetIndex (), column, item);
}


int BaseItemModel::columnCount (const QModelIndex&) const
{
  return _columns;
}


QVariant BaseItemModel::data (const QModelIndex& index, int role) const
{
  if (!index.isValid ())
    {
      return QVariant ();
    }

  BaseItem* item = static_cast<BaseItem*>(index.internalPointer ());
  if (!item || item == _root)
    {
      return QVariant ();
    }

  return item->GetData (index.column (), role);
}

QModelIndex BaseItemModel::index (int row, int column, const QModelIndex& parent) const
{
  BaseItem* parentItem = _root;
  if (parent.isValid ())
    {
      parentItem =  static_cast<BaseItem*>(parent.internalPointer ());
    }
  if (!parentItem)
    {
      return QModelIndex ();
    }

  if (row < 0 || row >= parentItem->GetNumberOfItems ())
    {
      return QModelIndex ();
    }

  return CreateModelIndex (parentItem->GetItem (row), column);
}

QModelIndex BaseItemModel::parent (const QModelIndex& index) const
{
  if (!index.isValid ())
    {
      return QModelIndex ();
    }

  BaseItem* item = static_cast<BaseItem*>(index.internalPointer ());
  if (!item || item == _root)
    {
      return QModelIndex ();
    }

  BaseItem* parentItem = item->GetParent();
  if (!parentItem || parentItem == _root)
    {
      return QModelIndex ();
    }

  return CreateModelIndex (parentItem);
}

int BaseItemModel::rowCount (const QModelIndex& index) const
{
  BaseItem* item = _root;
  if (index.isValid ())
    {
      item = static_cast<BaseItem*>(index.internalPointer ());
    }
  if (!item)
    {
      return 0;
    }

  return item->GetNumberOfItems ();
}
